package com.yt.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.*;

/**
 * 签名工具
 * url编码注意事项：
 * java：  +替换%20
 * js：
 * !----->%21
 * ~---->%7E
 * '----->%27
 * (---->%28
 * )---->%29
 * @author 解风
 * @version 2018-01-09
 */
@Slf4j
public class SignUtils {
    private static final int INT1000 = 1000;
    private static final String SIGNATURE = "signature";
    private static final int SECOND300 = 300;
    private static final String CONTENTENCODING = "UTF-8";

    /**
     * 验证接口参数签名
     * 所有参数都放入request的param中，不放入header里面，也不从header里面取参数
     * 参数signature不参在后台不参与签名，且参数长度大于1000的参数也不参与签名
     * public_key的字符串固定，参与签名计算
     * 同时还要校验时间是否超时
     * @param request HttpServletRequest
     * @return boolean
     *
     * 1、publicKey = F6888FAA84B6EC90320D5FCDF648BF4B
     * 2、timestamp 时间挫
     * 3、signature = MD5(publicKey+MD5(参数串)toUpperCase())
     * 4、参数串：放入一个map， 然后对map排序（顺序），组装参数串: key=URLEncoder(vulue)&key=URLEncoder(vulue)
     */
    public static boolean valiSignature(HttpServletRequest request) {
        //1、获取请求参数
        Map<String, String> paramMap = getParams(request);
        String paramsStr = getOrderParamString(paramMap);//排序后的参数串
        String signature = request.getParameter(SIGNATURE);// 签名信息
        String public_key = "F6888FAA84B6EC90320D5FCDF648BF4B";// public_key为“leawod”的md5值

        //2、后端签名
        if(StrUtils.isEmpty(paramsStr)){
            paramsStr = "";
        }
        String msg = public_key + Md5Utils.encryption(paramsStr).toUpperCase();
        String local_signature = Md5Utils.encryption(msg);
        //3、校验签名是否一致
//        long ts = Long.parseLong(paramMap.get("timestamp"));
//        boolean success = signature.equalsIgnoreCase(local_signature) && checkTimeOut(ts, SECOND300);
        boolean success = local_signature.equalsIgnoreCase(signature);
        if(!success){
            log.error("签名错误：第一次md5:" + paramsStr + "=====>第二次MD5:" + msg + "=====>public_key:" + public_key + "=====>客服端传的signature:" + signature + "=====>java signature：" + local_signature);

        }
        return success;
    }

    public static String createSign(String appId, String timestamp, String nonce, String data, String
            secretKey){
        StringBuilder sb = new StringBuilder();
        sb.append("appId=").append(appId);
        sb.append("&");
        sb.append("nonce=").append(nonce);
        sb.append("&");
        sb.append("secretKey=").append(secretKey);
        sb.append("&");
        if (StringUtils.hasLength(data)) {
            sb.append("encdata=").append(data);
            sb.append("&");
        }
        sb.append("timestamp=").append(timestamp);
        return Md5Utils.code(sb.toString());
    }

    private static Map<String,String> getParams(HttpServletRequest request){
        Map<String, String> urlParams = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        if(requestParams !=null){
            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
                String name = (String) iter.next();
                // 数据中心把signature字段放到request请求中，该字段不参与签名
                if(SIGNATURE.equalsIgnoreCase(name)) {
                    continue;
                }
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";

                int len = values.length;
                for (int i = 0; i < len; i++) {
                    // 当参数的值大于1000,不参与签名
                    if(values[i].length() > INT1000) {
                        continue;
                    }
                    valueStr = (i == len - 1) ? valueStr + values[i]  : valueStr + values[i] + ",";
                }
                urlParams.put(name, valueStr);
            }
        }
        return urlParams;
    }

    private static String getOrderParamString(Map<String, String> parms){
        StringBuffer sb = new StringBuffer();
        try {
            ArrayList<String> aa = new ArrayList<String>(parms.keySet());
            Collections.sort(aa);
            for (String key : aa) {
                sb.append(key).append("=").append(URLEncoder.encode(parms.get(key),"UTF-8").replaceAll("\\+", "%20")).append("&");
            }
            if (sb.length() > 1) {
                sb.deleteCharAt(sb.length()-1);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return sb.toString();
    }


    /**
     * client传递过来的时间，在正负5分钟内都有效
     * @param ts client传递过来的时间
     * @param second 秒
     * @return boolean
     */
    private static boolean checkTimeOut(long ts,int second) {
        Date date = new Date();
        long min = date.getTime() / 1000 - second;
        long max = date.getTime() / 1000 + second;
        return ts < min || ts > max;
    }

    public static String getSignature(Map<String, String> parms){
        String paramsStr = getOrderParamString(parms);//排序后的参数串
        String public_key = "F6888FAA84B6EC90320D5FCDF648BF4B";// public_key为“leawod”的md5值

        //2、后端签名
        log.info("---paramsStr------->"+paramsStr);
        if(StrUtils.isEmpty(paramsStr)){
            paramsStr = "";
        }
        log.info("---MD5-1------->"+ Md5Utils.encryption(paramsStr));

        String msg = public_key + Md5Utils.encryption(paramsStr).toUpperCase();
        log.info("---msg------->"+msg);
        String local_signature = Md5Utils.encryption(msg);
        return local_signature;
    }

    public static void main(String[] args) {
//        String paramsStr = "{\\\"salesAttributes\\\":[\\\"[]\\\"],\\\"formMessage\\\":[\\\"[{\\\\\\\"comboName\\\\\\\":\\\\\\\"钢板刷\\\\\\\",\\\\\\\"batchNumber\\\\\\\":\\\\\\\"100\\\\\\\",\\\\\\\"chang\\\\\\\":\\\\\\\"220\\\\\\\",\\\\\\\"commodityUnit\\\\\\\":\\\\\\\"378593306667515904\\\\\\\",\\\\\\\"gao\\\\\\\":\\\\\\\"25\\\\\\\",\\\\\\\"inventoryNumberWarning\\\\\\\":\\\\\\\"103\\\\\\\",\\\\\\\"inventoryNumber\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"kuan\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"price\\\\\\\":\\\\\\\"268\\\\\\\",\\\\\\\"shulian\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"wholesalePrice\\\\\\\":\\\\\\\"248\\\\\\\",\\\\\\\"originalPrice\\\\\\\":\\\\\\\"280\\\\\\\",\\\\\\\"setMeal\\\\\\\":true,\\\\\\\"commoditySize\\\\\\\":\\\\\\\"220x200x25\\\\\\\",\\\\\\\"commoditySizeUnit\\\\\\\":\\\\\\\"0\\\\\\\"}]\\\"],\\\"isInquiry\\\":[\\\"0\\\"],\\\"firstBalance\\\":[\\\"\\\"],\\\"combos\\\":[\\\"[{\\\\\\\"comboName\\\\\\\":\\\\\\\"钢板刷\\\\\\\",\\\\\\\"batchNumber\\\\\\\":\\\\\\\"100\\\\\\\",\\\\\\\"chang\\\\\\\":\\\\\\\"220\\\\\\\",\\\\\\\"commodityUnit\\\\\\\":\\\\\\\"378593306667515904\\\\\\\",\\\\\\\"gao\\\\\\\":\\\\\\\"25\\\\\\\",\\\\\\\"inventoryNumberWarning\\\\\\\":\\\\\\\"103\\\\\\\",\\\\\\\"inventoryNumber\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"kuan\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"price\\\\\\\":\\\\\\\"268\\\\\\\",\\\\\\\"shulian\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"wholesalePrice\\\\\\\":\\\\\\\"248\\\\\\\",\\\\\\\"originalPrice\\\\\\\":\\\\\\\"280\\\\\\\",\\\\\\\"setMeal\\\\\\\":true,\\\\\\\"commoditySize\\\\\\\":\\\\\\\"220x200x25\\\\\\\",\\\\\\\"commoditySizeUnit\\\\\\\":\\\\\\\"0\\\\\\\"}]\\\"],\\\"paramValues\\\":[\\\"[]\\\"],\\\"type\\\":[\\\"0\\\"],\\\"tailBalance\\\":[\\\"\\\"],\\\"availableArea\\\":[\\\"0\\\"],\\\"shopId\\\":[\\\"438746930072387584\\\"],\\\"brandId\\\":[\\\"439426202365722624\\\"],\\\"brandIdOne\\\":[\\\"418064270979366912\\\"],\\\"brandIdTwo\\\":[\\\"418065352535179264\\\"],\\\"categoryId\\\":[\\\"418039151972188160\\\"],\\\"commoditySizeUnit\\\":[\\\"0\\\"],\\\"warrantyMonth\\\":[\\\"12\\\"],\\\"productSpecificationUrl\\\":[\\\"\\\"],\\\"notes\\\":[\\\"<div><spanyes';font-size:15.984pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\">钢板刷（钢板束）主要由弹簧钢板折弯成型后交叉叠加组成（见下图），弹簧钢板的贴合力紧贴管片，\\\\r\\\\n</spanyes';font-size:15.984pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\"></div><div><spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\">同时兼顾盾构机前移产生的摩擦确保钢板耐磨。</spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\"></div><div><spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\"><br></spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\"></div><p><img style=\\\\\\\"max-width:100%;\\\\\\\" src=\\\\\\\"http://118.24.115.211:38809/group1/M04/00/1A/rBsACF_IVR6Aa8FvAAC1Tj9V3wQ519.jpg\\\\\\\"/></p>\\\"],\\\"commodityNumber\\\":[\\\"12\\\"],\\\"isVipDiscounts\\\":[\\\"0\\\"],\\\"sendAreaId\\\":[\\\"320583\\\"],\\\"sellerAddressId\\\":[\\\"439818328358387712\\\"],\\\"name\\\":[\\\"盾尾钢板刷\\\"],\\\"description\\\":[\\\"耐磨，抗疲劳，贴合力优良\\\"],\\\"sendDays\\\":[\\\"3\\\"],\\\"attrs\\\":[\\\"[]\\\"],\\\"productCertificateUrls\\\":[\\\"/group1/M01/00/1A/rBsACF_IVfOAPfRHAAKPMB9fy_U168.pdf\\\"],\\\"logoUrl\\\":[\\\"/group1/M04/00/1A/rBsACF_IVR6Aa8FvAAC1Tj9V3wQ519.jpg\\\"],\\\"logoUrls\\\":[\\\"/group1/M00/00/1A/rBsACF_IVTGAGl-_AAIHSSnzqW0206.jpg\\\"],\\\"filterIds\\\":[\\\"410826312354235232,410826312354234784,410827728636477504,442278854942392352,410827728636477760,410827728636477632,410827728636477664,410827728636477536,410827728636477440,410827728636477568,410827728636477472,410827728636477600,442278854934003744,442278854946586624,442278854929809408,410828619561173088,410828619561173472,410828946314231808,410828946314231840,410828946314231872,410829132637798400,410829132637798432,410829132637798464\\\"],\\\"paramList\\\":[\\\"[]\\\"],\\\"isNew\\\":[\\\"1\\\"],\\\"isRecommend\\\":[\\\"1\\\"],\\\"availableAreaName\\\":[\\\"全国\\\"],\\\"attrList\\\":[\\\"[]\\\"],\\\"comboList\\\":[\\\"[{\\\\\\\"comboName\\\\\\\":\\\\\\\"钢板刷\\\\\\\",\\\\\\\"batchNumber\\\\\\\":\\\\\\\"100\\\\\\\",\\\\\\\"chang\\\\\\\":\\\\\\\"220\\\\\\\",\\\\\\\"commodityUnit\\\\\\\":\\\\\\\"378593306667515904\\\\\\\",\\\\\\\"gao\\\\\\\":\\\\\\\"25\\\\\\\",\\\\\\\"inventoryNumberWarning\\\\\\\":\\\\\\\"103\\\\\\\",\\\\\\\"inventoryNumber\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"kuan\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"price\\\\\\\":\\\\\\\"268\\\\\\\",\\\\\\\"shulian\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"wholesalePrice\\\\\\\":\\\\\\\"248\\\\\\\",\\\\\\\"originalPrice\\\\\\\":\\\\\\\"280\\\\\\\",\\\\\\\"setMeal\\\\\\\":true,\\\\\\\"commoditySize\\\\\\\":\\\\\\\"220x200x25\\\\\\\",\\\\\\\"commoditySizeUnit\\\\\\\":\\\\\\\"0\\\\\\\"}]\\\"],\\\"signature\\\":[\\\"fdf797225dfa3b70e7a3a98b77284526\\\"]}";
//        String paramsStr = "{\\\"salesAttributes\\\":[\\\"[]\\\"],\\\"formMessage\\\":[\\\"[{\\\\\\\"comboName\\\\\\\":\\\\\\\"钢板刷\\\\\\\",\\\\\\\"batchNumber\\\\\\\":\\\\\\\"100\\\\\\\",\\\\\\\"chang\\\\\\\":\\\\\\\"220\\\\\\\",\\\\\\\"commodityUnit\\\\\\\":\\\\\\\"378593306667515904\\\\\\\",\\\\\\\"gao\\\\\\\":\\\\\\\"25\\\\\\\",\\\\\\\"inventoryNumberWarning\\\\\\\":\\\\\\\"103\\\\\\\",\\\\\\\"inventoryNumber\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"kuan\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"price\\\\\\\":\\\\\\\"268\\\\\\\",\\\\\\\"shulian\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"wholesalePrice\\\\\\\":\\\\\\\"248\\\\\\\",\\\\\\\"originalPrice\\\\\\\":\\\\\\\"280\\\\\\\",\\\\\\\"setMeal\\\\\\\":true,\\\\\\\"commoditySize\\\\\\\":\\\\\\\"220x200x25\\\\\\\",\\\\\\\"commoditySizeUnit\\\\\\\":\\\\\\\"0\\\\\\\"}]\\\"],\\\"isInquiry\\\":[\\\"0\\\"],\\\"firstBalance\\\":[\\\"\\\"],\\\"combos\\\":[\\\"[{\\\\\\\"comboName\\\\\\\":\\\\\\\"钢板刷\\\\\\\",\\\\\\\"batchNumber\\\\\\\":\\\\\\\"100\\\\\\\",\\\\\\\"chang\\\\\\\":\\\\\\\"220\\\\\\\",\\\\\\\"commodityUnit\\\\\\\":\\\\\\\"378593306667515904\\\\\\\",\\\\\\\"gao\\\\\\\":\\\\\\\"25\\\\\\\",\\\\\\\"inventoryNumberWarning\\\\\\\":\\\\\\\"103\\\\\\\",\\\\\\\"inventoryNumber\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"kuan\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"price\\\\\\\":\\\\\\\"268\\\\\\\",\\\\\\\"shulian\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"wholesalePrice\\\\\\\":\\\\\\\"248\\\\\\\",\\\\\\\"originalPrice\\\\\\\":\\\\\\\"280\\\\\\\",\\\\\\\"setMeal\\\\\\\":true,\\\\\\\"commoditySize\\\\\\\":\\\\\\\"220x200x25\\\\\\\",\\\\\\\"commoditySizeUnit\\\\\\\":\\\\\\\"0\\\\\\\"}]\\\"],\\\"paramValues\\\":[\\\"[]\\\"],\\\"type\\\":[\\\"0\\\"],\\\"tailBalance\\\":[\\\"\\\"],\\\"availableArea\\\":[\\\"0\\\"],\\\"shopId\\\":[\\\"438746930072387584\\\"],\\\"brandId\\\":[\\\"439426202365722624\\\"],\\\"brandIdOne\\\":[\\\"418064270979366912\\\"],\\\"brandIdTwo\\\":[\\\"418065352535179264\\\"],\\\"categoryId\\\":[\\\"418039151972188160\\\"],\\\"commoditySizeUnit\\\":[\\\"0\\\"],\\\"warrantyMonth\\\":[\\\"12\\\"],\\\"productSpecificationUrl\\\":[\\\"\\\"]" ;

//        String paramsStr = ",\\\"notes\\\":[\\\"<div><spanyes';font-size:15.984pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\">" ;
//         String paramsStr =  "钢板刷（钢板束）主要由弹簧钢板折弯成型后交叉叠加组成（见下图），弹簧钢板的贴合力紧贴管片，\\\\r\\\\n</spanyes';font-size:15.984pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\"></div><div><spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\">同时兼顾盾构机前移产生的摩擦确保钢板耐磨。</spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\">";
//        String paramsStr =   "</div><div><spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\"><br></spanyes';font-size:15.96pt;font-family:微软雅黑;color:rgb(0,0,0);\\\\\\\">" ;
//        String paramsStr = "</div><p><img style=\\\\\\\"max-width:100%;\\\\\\\" src=\\\\\\\"http://118.24.115.211:38809/group1/M04/00/1A/rBsACF_IVR6Aa8FvAAC1Tj9V3wQ519.jpg\\\\\\\"/>";
//        String paramsStr = "</p>\\\"],\\\"commodityNumber\\\":[\\\"12\\\"],\\\"isVipDiscounts\\\":[\\\"0\\\"]" ;
//        String paramsStr =",\\\"sendAreaId\\\":[\\\"320583\\\"],\\\"sellerAddressId\\\":[\\\"439818328358387712\\\"],\\\"name\\\":[\\\"盾尾钢板刷\\\"],\\\"description\\\":[\\\"耐磨，抗疲劳，贴合力优良\\\"],\\\"sendDays\\\":[\\\"3\\\"],\\\"attrs\\\":[\\\"[]\\\"],\\\"productCertificateUrls\\\":[\\\"/group1/M01/00/1A/rBsACF_IVfOAPfRHAAKPMB9fy_U168.pdf\\\"],\\\"logoUrl\\\":[\\\"/group1/M04/00/1A/rBsACF_IVR6Aa8FvAAC1Tj9V3wQ519.jpg\\\"],\\\"logoUrls\\\":[\\\"/group1/M00/00/1A/rBsACF_IVTGAGl-_AAIHSSnzqW0206.jpg\\\"],\\\"filterIds\\\":[\\\"410826312354235232,410826312354234784,410827728636477504,442278854942392352,410827728636477760,410827728636477632,410827728636477664,410827728636477536,410827728636477440,410827728636477568,410827728636477472,410827728636477600,442278854934003744,442278854946586624,442278854929809408,410828619561173088,410828619561173472,410828946314231808,410828946314231840,410828946314231872,410829132637798400,410829132637798432,410829132637798464\\\"],\\\"paramList\\\":[\\\"[]\\\"],\\\"isNew\\\":[\\\"1\\\"],\\\"isRecommend\\\":[\\\"1\\\"],\\\"availableAreaName\\\":[\\\"全国\\\"],\\\"attrList\\\":[\\\"[]\\\"],\\\"comboList\\\":[\\\"[{\\\\\\\"comboName\\\\\\\":\\\\\\\"钢板刷\\\\\\\",\\\\\\\"batchNumber\\\\\\\":\\\\\\\"100\\\\\\\",\\\\\\\"chang\\\\\\\":\\\\\\\"220\\\\\\\",\\\\\\\"commodityUnit\\\\\\\":\\\\\\\"378593306667515904\\\\\\\",\\\\\\\"gao\\\\\\\":\\\\\\\"25\\\\\\\",\\\\\\\"inventoryNumberWarning\\\\\\\":\\\\\\\"103\\\\\\\"";
        String paramsStr =   ",\\\\\\\"inventoryNumber\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"kuan\\\\\\\":\\\\\\\"200\\\\\\\",\\\\\\\"price\\\\\\\":\\\\\\\"268\\\\\\\",\\\\\\\"shulian\\\\\\\":\\\\\\\"\\\\\\\",\\\\\\\"wholesalePrice\\\\\\\":\\\\\\\"248\\\\\\\",\\\\\\\"originalPrice\\\\\\\":\\\\\\\"280\\\\\\\",\\\\\\\"setMeal\\\\\\\":true,\\\\\\\"commoditySize\\\\\\\":\\\\\\\"220x200x25\\\\\\\",\\\\\\\"commoditySizeUnit\\\\\\\":\\\\\\\"0\\\\\\\"}]\\\"],\\\"signature\\\":[\\\"fdf797225dfa3b70e7a3a98b77284526\\\"]}";

//        String s1 = StringEscapeUtils.unescapeJava("%7E");
//        paramsStr = StringEscapeUtils.unescapeJava(paramsStr);
//        //String signature = "D07D09514442CB57BCBD9C6411361238";// 签名信息
//        String signature = "E469DEE445C75D2E316B126FF4F417B8";// 签名信息
//        String public_key = "F6888FAA84B6EC90320D5FCDF648BF4B";// public_key为“leawod”的md5值
//        String msg = public_key + Md5Utils.encryption(paramsStr).toUpperCase();
//        String local_signature = Md5Utils.encryption(msg);
//        boolean success = signature.equalsIgnoreCase(local_signature);

        String s = "A-Z a-z 0-9 - _ . ! ~ * ' ( )27%+";
//        String s = "~";
        try{
            String ss = URLEncoder.encode(s,"UTF-8");
//            String ss = URLEncoder.encode(s,"UTF-8").replaceAll("\\+", "%20");
            System.out.println(ss);
            System.out.println(Md5Utils.encryption(ss));
        } catch (Exception e){
            e.printStackTrace();
        }


    }
}
